package com.ymt.bpm.service.engine.task.impl;

import com.alibaba.fastjson.JSONObject;
import com.ymt.bpm.dao.MDao;
import com.ymt.bpm.dao.Mapper;
import com.ymt.bpm.model.PNotify;
import com.ymt.bpm.model.PPi;
import com.ymt.bpm.model.PTaskTodo;
import com.ymt.bpm.service.engine.task.NotifyService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Created by Johnny on 2017/4/22.
 */
@Service
public class NotifyServiceImpl implements NotifyService {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    private BeanCopier copier = BeanCopier.create(PNotify.class, PNotify.class, false);

    @Autowired
    private MDao dao;

    public int recordTodoNotify(String tenantId,
                                 JSONObject bpmnConfig,
                                 JSONObject activityConf,
                                 PTaskTodo todo, PPi pi) {


        PNotify notify = new PNotify();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) notify.setTenantId(Integer.parseInt(tenantId));
        notify.setPiEid(todo.getPiEid());
        notify.setTiId(todo.getTiId());
        notify.setStatus("0");

        //下面为待办任务提醒所需属性
        notify.setCreateTime(todo.getCreateTime());
//		notify.setSender(todo.getUserId());	//非手工提醒不需要sender
//		notify.setSenderName(todo.getUserName());
        notify.setReceiver(todo.getUserId());
        notify.setReceiverName(todo.getUserName());
        //content
        String content = pi.getBpdName() +" - "+ todo.getActivityName();
        notify.setContent(content);

        List<PNotify> notifies = new ArrayList<PNotify>();

        //新任务提醒
        String newTaskRemind = activityConf.getString("newTaskRemind");
        if ("1".equals(newTaskRemind)) {
            String newTaskRemindMethods = activityConf.getString("newTaskRemindMethods");
            if (newTaskRemindMethods!=null) {
                if (newTaskRemindMethods.indexOf("email")>=0) {
                    PNotify notify1 = clone(notify);
                    notify1.setId(UUID.randomUUID().toString());
                    notify1.setType(PNotify.TYPE_MAIL);
                    notify1.settType(PNotify.TTYPE_NEW);
                    notifies.add(notify1);
                }
                if (newTaskRemindMethods.indexOf("msg")>=0) {
                    PNotify notify1 = clone(notify);
                    notify1.setId(UUID.randomUUID().toString());
                    notify1.setType(PNotify.TYPE_MSG);
                    notify1.settType(PNotify.TTYPE_NEW);
                    notifies.add(notify1);
                }
            }
        }

        //到期提醒时间单位
        String timelineUnitStr = bpmnConfig.getJSONObject("Collaboration_1").getString("timelineUnit");

        //任务到期提醒
        String remind = activityConf.getString("remind");
        if ("1".equals(remind)) {
            //提醒方式
            String remindmethods = activityConf.getString("remindmethods");
            if (remindmethods!=null) {
                //到期时间周期
                String durationStr = activityConf.getString("duration");
                //到期时间点
                Date expireTime = getExpireTime(todo.getCreateTime(),
                        timelineUnitStr,
                        durationStr);
                //提前提醒时间周期
                String remindtimeStr = activityConf.getString("remindtime");
                //提前提醒单位
                String remindunitStr = activityConf.getString("remindunit");
                //提前提醒时间点
                Date remindTime = getRemindTime(expireTime, remindunitStr, remindtimeStr);

                if (remindmethods.indexOf("email")>=0) {
                    //到期提醒
                    PNotify notify1 = clone(notify);
                    notify1.setId(UUID.randomUUID().toString());
                    notify1.setType(PNotify.TYPE_MAIL);
                    notify1.settType(PNotify.TTYPE_DUE);
                    notify1.setExpireTime(expireTime);
                    notify1.setScheduleTime(expireTime);
                    notifies.add(notify1);
                    //提前到期警告
                    PNotify notify2 = clone(notify);
                    notify2.setId(UUID.randomUUID().toString());
                    notify2.setType(PNotify.TYPE_MAIL);
                    notify2.settType(PNotify.TTYPE_DUE);
                    notify2.setExpireTime(remindTime);
                    notify2.setScheduleTime(remindTime);
                    notifies.add(notify2);
                }
                if (remindmethods.indexOf("msg")>=0) {
                    //到期提醒
                    PNotify notify1 = clone(notify);
                    notify1.setId(UUID.randomUUID().toString());
                    notify1.setType(PNotify.TYPE_MSG);
                    notify1.settType(PNotify.TTYPE_DUE);
                    notify1.setExpireTime(expireTime);
                    notify1.setScheduleTime(expireTime);
                    notifies.add(notify1);
                    //提前到期警告
                    PNotify notify2 = clone(notify);
                    notify2.setId(UUID.randomUUID().toString());
                    notify2.setType(PNotify.TYPE_MSG);
                    notify2.settType(PNotify.TTYPE_DUE);
                    notify2.setExpireTime(remindTime);
                    notify2.setScheduleTime(remindTime);
                    notifies.add(notify2);
                }
            }
        }

        //流程到期提醒 - 给待办任务参与者
        getPiNotifies(notify,
                notifies,
                timelineUnitStr,
                bpmnConfig,
                pi);

        return dao.batchInsert(Mapper.PNotifyMapper, "insertSelective", notifies);
    }

    /**
     * 记录流程到期提醒，给发起人
     * @param tenantId
     * @param bpmnConfig
     * @param pi
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public int recordPiNotify(String tenantId,
                               JSONObject bpmnConfig, PPi pi) {

        PNotify notify = new PNotify();
        if (tenantId!=null && StringUtils.isNumeric(tenantId)) notify.setTenantId(Integer.parseInt(tenantId));
        notify.setPiEid(pi.getPiEid());
        notify.setStatus("0");

        //下面为待办任务提醒所需属性
        notify.setCreateTime(pi.getCreateTime());
        notify.setReceiver(pi.getUserId());
        notify.setReceiverName(pi.getUserName());
        notify.setContent(pi.getBpdName());

        //到期提醒时间单位
        String timelineUnitStr = bpmnConfig.getJSONObject("Collaboration_1").getString("timelineUnit");

        List<PNotify> notifies = new ArrayList<PNotify>();
        getPiNotifies(notify,
                notifies,
                timelineUnitStr,
                bpmnConfig,
                pi);

        return dao.batchInsert(Mapper.PNotifyMapper, "insertSelective", notifies);
    }

    private void getPiNotifies(PNotify notify,
                               List<PNotify> notifies,
                               String timelineUnitStr,
                               JSONObject bpmnConfig,
                               PPi pi) {

        String pi_remind = bpmnConfig.getJSONObject("Collaboration_1").getString("remind");
        if ("1".equals(pi_remind)) {

            //提醒方式
            String remindmethods = bpmnConfig.getJSONObject("Collaboration_1").getString("remindmethods");
            if (remindmethods!=null) {
                //到期时间周期
                String durationStr = bpmnConfig.getJSONObject("Collaboration_1").getString("duration");
                //到期时间点
                Date expireTime = getExpireTime(pi.getCreateTime(),
                        timelineUnitStr,
                        durationStr);
                //提前提醒时间周期
                String remindtimeStr = bpmnConfig.getJSONObject("Collaboration_1").getString("remindtime");
                //提前提醒单位
                String remindunitStr = bpmnConfig.getJSONObject("Collaboration_1").getString("remindunit");
                //提前提醒时间点
                Date remindTime = getRemindTime(expireTime, remindunitStr, remindtimeStr);

                if (remindmethods.indexOf("email")>=0) {
                    //到期提醒
                    PNotify notify1 = clone(notify);
                    notify1.setId(UUID.randomUUID().toString());
                    notify1.setType(PNotify.TYPE_MAIL);
                    notify1.settType(PNotify.TTYPE_PI);
                    notify1.setExpireTime(expireTime);
                    notify1.setScheduleTime(expireTime);
                    notifies.add(notify1);
                    //提前到期警告
                    PNotify notify2 = clone(notify);
                    notify2.setId(UUID.randomUUID().toString());
                    notify2.setType(PNotify.TYPE_MAIL);
                    notify2.settType(PNotify.TTYPE_PI);
                    notify2.setExpireTime(remindTime);
                    notify2.setScheduleTime(remindTime);
                    notifies.add(notify2);
                }
                if (remindmethods.indexOf("msg")>=0) {
                    //到期提醒
                    PNotify notify1 = clone(notify);
                    notify1.setId(UUID.randomUUID().toString());
                    notify1.setType(PNotify.TYPE_MSG);
                    notify1.settType(PNotify.TTYPE_PI);
                    notify1.setExpireTime(expireTime);
                    notify1.setScheduleTime(expireTime);
                    notifies.add(notify1);
                    //提前到期警告
                    PNotify notify2 = clone(notify);
                    notify2.setId(UUID.randomUUID().toString());
                    notify2.setType(PNotify.TYPE_MSG);
                    notify2.settType(PNotify.TTYPE_PI);
                    notify2.setExpireTime(remindTime);
                    notify2.setScheduleTime(remindTime);
                    notifies.add(notify2);
                }
            }
        }
    }

    /**
     * 获取到期时间
     * @param createTime
     * @param timelineUnitStr
     * @param durationStr
     * @return
     */
    private Date getExpireTime(Date createTime,
                               String timelineUnitStr,
                               String durationStr) {
        int duration = Integer.parseInt(durationStr);
        if ("day".equals(timelineUnitStr)) {
            return new Date(createTime.getTime() + duration * 86400000l);
        } else if ("hour".equals(timelineUnitStr)) {
            return new Date(createTime.getTime() + duration * 3600000l);
        }
        return null;
    }

    /**
     * 获取提前提醒时间
     * @param expireTime
     * @param remindunitStr
     * @param remindtimeStr
     * @return
     */
    private Date getRemindTime(Date expireTime,
                               String remindunitStr,
                               String remindtimeStr) {
        int duration = Integer.parseInt(remindtimeStr);
        if ("day".equals(remindunitStr)) {
            return new Date(expireTime.getTime() - duration * 86400000l);
        } else if ("hour".equals(remindunitStr)) {
            return new Date(expireTime.getTime() - duration * 3600000l);
        }
        return null;
    }

    private PNotify clone(PNotify notify) {
        PNotify notify1 = new PNotify();
        copier.copy(notify, notify1, null);
        return notify1;
    }
}
